package com.njust.RateMyTray_backend.service.impl.storage;

import com.njust.RateMyTray_backend.common.CustomException;
import com.njust.RateMyTray_backend.service.storage.StorageService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.UUID;

@Service
public class FileSystemStorageService implements StorageService {

    private final Path rootLocation;

    public FileSystemStorageService(@Value("${file.upload-dir}") String uploadDir) {
        this.rootLocation = Paths.get(uploadDir);
        try {
            Files.createDirectories(rootLocation);
        } catch (IOException e) {
            throw new CustomException("无法初始化文件存储目录", e);
        }
    }

    @Override
    public String store(MultipartFile file, String subDirectory) {
        if (file.isEmpty()) {
            throw new CustomException("无法存储空文件");
        }
        
        // 1. 生成唯一的文件名以避免冲突
        String originalFilename = StringUtils.cleanPath(file.getOriginalFilename());
        String extension = StringUtils.getFilenameExtension(originalFilename);
        String uniqueFilename = UUID.randomUUID().toString() + "." + extension;

        // 2. 创建子目录 (如果不存在)
        Path subDirLocation = this.rootLocation.resolve(subDirectory);
        try {
            Files.createDirectories(subDirLocation);
        } catch (IOException e) {
            throw new CustomException("无法创建子目录", e);
        }

        // 3. 将文件保存到目标位置
        Path destinationFile = subDirLocation.resolve(Paths.get(uniqueFilename))
                .normalize().toAbsolutePath();

        if (!destinationFile.getParent().equals(subDirLocation.toAbsolutePath())) {
            // 防止目录遍历攻击
            throw new CustomException("无法将文件存储在指定目录之外");
        }

        try (InputStream inputStream = file.getInputStream()) {
            Files.copy(inputStream, destinationFile, StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException e) {
            throw new CustomException("存储文件失败", e);
        }

        // 4. 返回可公开访问的相对URL路径
        return "/upload/" + subDirectory + "/" + uniqueFilename;
    }
} 